<chapter xml:id="posix.mutex.h">
<title><tt>__vic/posix/mutex.h</tt></title>


<chapter xml:id="posix--mutex">
<title><tt>posix::mutex</tt></title>

<code-block lang="C++"><![CDATA[
class posix::mutex
{
public:
    constexpr mutex() noexcept;
    ~mutex();

    mutex(const mutex & ) = delete;
    mutex &operator=(const mutex & ) = delete;

    void lock();
    bool try_lock();
    bool unlock() noexcept;

    // System-specific handle
    ::pthread_mutex_t *handle();
    const ::pthread_mutex_t *handle() const;
};
]]></code-block>

<p>Обёртка для простого нерекурсивного <tt>pthread_mutex_t</tt>. См. замечания
по использованию в <xref to="mutex"/>.</p>

<section><title>Члены класса</title>

<synopsis>
<prototype>constexpr mutex() noexcept</prototype>
<p>Создаёт незаблокированный мьютекс.</p>
</synopsis>

<synopsis>
<prototype>~mutex()</prototype>
<p>Уничтожает мьютекс.</p>
</synopsis>

<synopsis>
<prototype>void lock()</prototype>
<p>Захватывает блокировку на мьютексе. Ждёт его освобождения, если он уже
захвачен другим потоком в данный момент.</p>
</synopsis>

<synopsis>
<prototype>bool try_lock()</prototype>
<p>Пытается захватить мьютекс. Немедленно возвращает <tt>false</tt> без
ожидания, если он уже захвачен другим потоком.</p>
</synopsis>

<synopsis>
<prototype>bool unlock() noexcept</prototype>
<p>Освобождает ранее захваченный мьютекс. Иногда может возвращать <tt>false</tt>
в случае ошибок, но в общем случае обнаружение ошибок не гарантируется.</p>
</synopsis>

<synopsis>
<prototype>::pthread_mutex_t *handle()</prototype>
<prototype>const ::pthread_mutex_t *handle() const</prototype>
<p>Возвращает системный дескриптор мьютекса.</p>
</synopsis>

</section>

<section><title>Пример</title>
<p>См. <xref to="posix--mutex_lock"/>.</p>
</section>

</chapter>


<chapter xml:id="posix--mutex_lock">
<title><tt>posix::mutex_lock</tt></title>

<code-block lang="C++"><![CDATA[
class posix::mutex_lock : private non_copyable, private non_heap_allocatable
{
public:
    enum adopt_t { adopt };

    explicit mutex_lock(posix::mutex &mtx);
    mutex_lock(posix::mutex &mtx, adopt_t);

    explicit mutex_lock(::pthread_mutex_t &mtx);
    mutex_lock(::pthread_mutex_t &mtx, adopt_t);

    ~mutex_lock() noexcept(false);
};
]]></code-block>

<p>Управляет блокировкой на мьютексе. Снимает блокировку по окончании времени
жизни объекта. Способен работать как с <tt>posix::mutex</tt>, так и с системным
<tt>pthread_mutex_t</tt>.</p>

<section><title>Члены класса</title>

<synopsis>
<prototype>adopt</prototype>
<p>Тэг конструктора, подавляет захват мьютекса.</p>
</synopsis>

<synopsis>
<prototype>explicit mutex_lock(posix::mutex &amp;mtx)</prototype>
<prototype>explicit mutex_lock(::pthread_mutex_t &amp;mtx)</prototype>
<p>Захватывает <tt>mtx</tt>.</p>
</synopsis>

<synopsis>
<prototype>~mutex_lock() noexcept(false)</prototype>
<p>Освобождает <tt>mtx</tt>. Может бросить исключение, если произошла ошибка
и нет другого активного исключения!</p>
</synopsis>

<synopsis>
<prototype>mutex_lock(posix::mutex &amp;mtx, adopt_t)</prototype>
<prototype>mutex_lock(::pthread_mutex_t &amp;mtx, adopt_t)</prototype>
<p>Принимает уже захваченный <tt>mtx</tt>. См. пример.</p>
</synopsis>

</section>

<section><title>Пример</title>
<code-block lang="C++">
// Типичное использование
void reentrant_function()
{
    static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
    __vic::posix::mutex_lock lock(mtx);
    // Критическая секция до конца этого блока
    ...
}

// Использование незахватывающего конструктора
__vic::posix::mutex mtx;
if(mtx.try_lock()) // Пытаемся захватить мьютекс
{
    // Мьютекс успешно захвачен
    using __vic::posix::mutex_lock;
    mutex_lock lock(mtx, mutex_lock::adopt);
    // Критическая секция до конца этого блока
    ...
}
else
{
    // Мьютекс удерживается другим потоком
    ...
}
</code-block>
</section>

</chapter>


</chapter>
